/**
	License:		Artistic license 2.0 (see license.txt, also available online at http://www.perlfoundation.org/artistic_license_2_0)
	Authors:		OrbitalLab (http://www.orbitallab.ru/moonglide/), 2007-2009

	File:			Factory.d
	Description:	factory system for game objects & gui
	Date:			17.05.2008 by Digited
*/
module moonglide.core.Factory;

import
	moonglide.core.Events;

//=============================================================
/// interface of an object, produceable by its factory
//=============================================================
interface IProduct : IEventGenerator, IEventListener
{
	void Serialize();
}

//=============================================================
/// abstract product settings class
//=============================================================
abstract class CProductSettings
{
	mixin TDynamicProperties;

	protected:
		this() {}

	public:
		static CProductSettings opCall()
		{
			return null; //new CProductSettings;
		}

		~this() {}
}

//=============================================================
/// abstract product factory class
//=============================================================
abstract class CProductFactory : IMoonGlideObject
{
	mixin TMoonGlideObject;

	public:
		IProduct opCall( CProductSettings settings, IProduct product = null )
		{
			// if product is null, factory must construct its product
			// else means given product is down the class ierarchy
			return product;
		}

		this( char[] id )
		{
			_id = id;
			CFactoryManager().Register( this );
		}
}

//=============================================================
/// Factory Manager - keeps and gives access to all registered factories
//=============================================================
class CFactoryManager
{
	protected:
		CProductFactory[char[]]	_factories;

		this() {}
		static CFactoryManager	_singleton;

	public:
		static CFactoryManager opCall()
		{
			if( _singleton is null )
				_singleton = new CFactoryManager;

			return _singleton;
		}

		bool Register( CProductFactory factory )
		{
			if( !(factory.id in _factories ))
			{
				_factories[ factory.id ] = factory;
				return true;
			}
			else
				return false;
		}

		~this() {}
}
